#pragma once
#include <ctype.h>
#include <inttypes.h>
#include "DirectoryListing.h"
#include "DirectoryTree.h"
#include "DirectoryEntryWithTree.h"
#include "Options.h"
#include "FileToMove.h"
#include "SortedList.h"
#include "gstring.h"
class FileCopier
{
public:	
	/// <summary>
	/// Method that's called from main to start copying files.
	/// </summary>
	/// <param name="argc">argc parameter from main</param>
	/// <param name="argv">argv parameter from main</param>
	/// <param name="version">Version to show the user</param>
	/// <returns></returns>
	static int RunCopier(int argc, gchar* argv[], double version);
private:
	/// <summary>
	/// Recursive function to copy files. Called from itself and RunCopier(int argc, gchar* argv[]).
	/// </summary>
	/// <param name="source">Source folder</param>
	/// <param name="target">Target folder</param>
	/// <param name="startPercentComplete">Start percent complete</param>
	/// <param name="endPercentComplete">End percent complete</param>
	/// <param name="howManyFilesCopied">Total number of files copied</param>
	/// <param name="howManyBytesCopied">Total number of bytes copied</param>
	/// <param name="howManyFilesDeleted">Total number of files deleted</param>
	/// <param name="options">Options from the main program such as don't actually change files</param>
	/// <returns></returns>
	static bool RunCopier(const gstring& source, const gstring& target, double startPercentComplete, double endPercentComplete, int& howManyFilesCopied, INT64& howManyBytesCopied, INT64& howManyFilesDeleted, Options& options);
	/// <summary>
	/// Copies all the changed files in a directory. Does not use recursion.
	/// </summary>
	/// <param name="source">Source folder</param>
	/// <param name="sourceListing">Directory list of source folder</param>
	/// <param name="target">Target folder</param>
	/// <param name="targetListing">Directory list of target folder</param>
	/// <param name="startPercentComplete">Start percent complete</param>
	/// <param name="endPercentComplete">End percent complete</param>
	/// <param name="howManyFilesCopied">Total number of files copied.</param>
	/// <param name="howManyBytesCopied">Total number of bytes copied.</param>
	/// <param name="options">Options from the main program such as don't actually change files</param>
	/// <returns></returns>
	static bool CopyChangedFiles(const gstring& source, DirectoryListing& sourceListing, const gstring& target, DirectoryListing& targetListing, double startPercentComplete, double endPercentComplete, int& howManyFilesCopied, INT64& howManyBytesCopied, Options& options);
	/// <summary>
	/// Deletes a directory and all the files and subdirectories in that directory.
	/// </summary>
	/// <param name="directory">Directory to delete</param>
	/// <param name="howManyFilesDeleted">How many files were deleted</param?
	/// <param name="options">Options from the main program such as don't actually change files.</param>
	/// <returns></returns>
	static bool DeleteDirectoryAndEverythingInIt(const gstring& directory, INT64& howManyFilesDeleted, Options& options);
	/// <summary>
	/// Copy all the files from the source folder to the target folder. Don't copy files alredy there.
	/// </summary>
	/// <param name="source">Source folder to read from.</param>
	/// <param name="target">Target folder to write to.</param>
	/// <param name="options">Options from the main program such as don't actually change files.</param>
	static void RunCopier(const gstring& source, const gstring& target, Options& options);
	/// <summary>
	/// If someone runs this program, then moves files/folders around in the source folder, find those files in the target folder and move them around the same way instead of copying them over again.
	/// </summary>
	/// <param name="source">Source folder</param>
	/// <param name="target">Target folder</param>
	/// <param name="howManyFilesDeleted">How many files this method deleted.</param>
	/// <param name="options">Options from the main program such as don't actually change files.</param>
	/// <returns></returns>
	static size_t FindFilesToMoveAndMoveThem(const gstring& source, const gstring& target, INT64& howManyFilesDeleted, Options& options);
	/// <summary>
	/// Move a list of files from one part of the target folder to another part. This is useful because sometimes someone moved files in the source folder. Move is faster than copy.
	/// </summary>
	/// <param name="filesToMove">List of files to move.</param>
	/// <param name="howManyFilesDeleted">Number of files this method deleted.</param>
	/// <param name="options">Options from the main program such as don't actually change files.</param>
	static void MoveFiles(list<FileToMove*>& filesToMove, INT64& howManyFilesDeleted, Options& options);
	/// <summary>
	/// Move a file. Create the target folder if it doesn't exist.
	/// </summary>
	/// <param name="sourcePath">Source file with full path.</param>
	/// <param name="targetPath">Target file with full path.</param>
	/// <param name="foldersCreated">Running list of folders either newly created or known to already exist.</param>
	/// <param name="options">Options from the main program such as don't actually change files.</param>
	static void MoveFileCreateTargetFolder(const gstring& sourcePath, const gstring& targetPath, SortedList<gstring>** foldersCreated, Options& options);
	/// <summary>
	/// Calculate where a target file should be moved to based on where it is and the source folder.
	/// </summary>
	/// <param name="source">File with directory location on the source drive</param>
	/// <param name="target">File with directory location on the target drive</param>
	/// <param name="newTargetPath">Output of where the new target file name with full path will be.</param>
	static void CalculateNewPathForMovedFile(DirectoryEntryWithTree* source, DirectoryEntryWithTree* target, gstring& newTargetPath);
};